package com.khstudio.videocapture.view;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.widget.ImageButton;

import com.khstudio.api.util.KhLog;
import com.khstudio.videocapture.R;

public class VideoSeekBarLayout_Kh extends ViewGroup {
    private static final int MSG_LONG_PRESS     = 0x0001;
    private static final int MSG_CHANGE_THUMB   = 0x0002;

    private static final int THUMB_JOIN     = 0x0000;
    private static final int THUMB_DISJOIN  = 0x0001;

    private Context mContext;
    private long    mDuration;

    private VideoSeekBarView_Kh  mBar;
    private ImageButton     mFrontThumb;
    private ImageButton     mRearThumb;
    private ImageButton     mPlayThumb;

    private int             mBarMaxWidth;
    private int             mFrontThumbPosX;
    private int             mRearThumbPosX;
    private int             mPlayThumbPosX;

    private int             mThumbMode;

    private VideoSeekBarLayoutListener_Kh mListener;

    public interface VideoSeekBarLayoutListener_Kh {
        void onChangeThumb(long c);
    }

    private final Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_LONG_PRESS : {
                    KhLog.e("MSG_LONG_PRESS");
                    _doThumbModeChange();
                } break;

                case MSG_CHANGE_THUMB : {
                    long c = (long) (((double)msg.arg1 / mBarMaxWidth) * mDuration);
                    KhLog.i("MSG_CHANGE_THUMB %d", c);
                    if(mListener != null) mListener.onChangeThumb(c);
                }
            }
        }
    };

    public VideoSeekBarLayout_Kh(Context context) {
        this(context, null);
    }

    public VideoSeekBarLayout_Kh(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public VideoSeekBarLayout_Kh(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        this.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {

            }
        });

        mContext = context;
        mDuration = 0;

        mBar = new VideoSeekBarView_Kh(mContext);
        addView(mBar);

        mFrontThumb = new ImageButton(mContext);
        mFrontThumb.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
        mFrontThumb.setBackgroundColor(Color.TRANSPARENT);
        mFrontThumb.setImageResource(R.drawable.kh_api_seekbar_thumb_left);
        mFrontThumb.setPadding(0, 0, 0, 0);
        mFrontThumb.setOnTouchListener(thumbTouchListener);
        mFrontThumb.setVisibility(View.VISIBLE);
        mFrontThumbPosX = 0;
        addView(mFrontThumb);

        mRearThumb = new ImageButton(mContext);
        mRearThumb.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
        mRearThumb.setBackgroundColor(Color.TRANSPARENT);
        mRearThumb.setImageResource(R.drawable.kh_api_seekbar_thumb_right);
        mRearThumb.setPadding(0, 0, 0, 0);
        mRearThumb.setOnTouchListener(thumbTouchListener);
        mRearThumb.setVisibility(View.VISIBLE);
        mRearThumbPosX = 0;
        addView(mRearThumb);

        mPlayThumb = new ImageButton(mContext);
        mPlayThumb.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
        mPlayThumb.setBackgroundColor(Color.TRANSPARENT);
        mPlayThumb.setImageResource(R.drawable.kh_api_seekbar_thumb_play);
        mPlayThumb.setPadding(0, 0, 0, 0);
        mPlayThumb.setOnTouchListener(thumbTouchListener);
        mPlayThumb.setVisibility(View.GONE);
        mPlayThumbPosX = 0;
        addView(mPlayThumb);

        mListener = null;

        int typeValue = TypedValue.COMPLEX_UNIT_DIP;
        DisplayMetrics metrics = mContext.getResources().getDisplayMetrics();

        mLongPressBoundary = (int) TypedValue.applyDimension(typeValue, 10, metrics);
        mDoubleTapBoundary = (int) TypedValue.applyDimension(typeValue, 10, metrics);

        mThumbMode = THUMB_JOIN;

        _initAttribute(attrs, defStyle);
    }

    public void setOnVideoSeekBarLayoutListener(VideoSeekBarLayoutListener_Kh l) {
        mListener = l;
    }

    public void setPlayTimeMs(long timeMs) {
        if(mThumbMode == THUMB_JOIN) {
            mFrontThumbPosX = (int) (((double) timeMs / mDuration) * mBarMaxWidth);
            mRearThumbPosX = mFrontThumbPosX;
        } else if(mThumbMode == THUMB_DISJOIN) {
            mPlayThumbPosX = (int) (((double) timeMs / mDuration) * mBarMaxWidth);
        }
        requestLayout();
    }

    public void setDuration(long duration) {
        mDuration = duration;
    }

    public long getUnitMs() {
        long c = (long) (((double)1 / mBarMaxWidth) * mDuration);
        return c > 0 ? c : 1;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        measureChildren(widthMeasureSpec, heightMeasureSpec);

        mBar.setPadding(mFrontThumb.getMeasuredWidth(), 0, mRearThumb.getMeasuredWidth(), 0);
        int newHeightSize = mFrontThumb.getMeasuredHeight() > mBar.getMeasuredHeight() ? mFrontThumb.getMeasuredHeight() : mBar.getMeasuredHeight();
        int newHeightMeasureSpec = MeasureSpec.makeMeasureSpec(newHeightSize, MeasureSpec.getMode(heightMeasureSpec));

        super.onMeasure(widthMeasureSpec, newHeightMeasureSpec);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {

            KhLog.v("VideoSeekBarLayout_Kh : onLayout changed = %b l = %d t = %d r = %d b = %d", changed, l, t, r, b);
            int width = r - l;
            int height = b - t;

            int left = 0;
            int top = 0;
            int right = 0;
            int bottom = 0;

            int padding_l = getPaddingLeft();
            int padding_t = getPaddingTop();
            int padding_r = getPaddingRight();
            int padding_b = getPaddingBottom();
            KhLog.v("VideoSeekBarLayout_Kh : onLayout padding l = %d t = %d r = %d b = %d", padding_l, padding_t, padding_r, padding_b);

            mBarMaxWidth = width;

            if(mBar != null) {
                mBarMaxWidth = mBar.getBarMaxWidth();
                left = padding_l;
                top = padding_t + (height - mBar.getMeasuredHeight()) / 2;
                right = left + mBar.getMeasuredWidth();
                bottom = top + mBar.getMeasuredHeight();
                KhLog.v("VideoSeekBarLayout_Kh : onLayout mBar l = %d t = %d r = %d b = %d", left, top, right, bottom);
                mBar.layout(left, top, right, bottom);

                mBar.setThumbPosition(mFrontThumbPosX, mRearThumbPosX);
            }

            if(mFrontThumb != null) {
                left = (int) (padding_l + mBar.getBarStartPosition() - mFrontThumb.getMeasuredWidth() + mFrontThumbPosX);
                top = padding_t + (height - mFrontThumb.getMeasuredHeight()) / 2;
                right = left + mFrontThumb.getMeasuredWidth();
                bottom = top + mFrontThumb.getMeasuredHeight();
                mFrontThumb.layout(left, top, right, bottom);
            }

            if(mRearThumb != null) {
                left = (int) (padding_l + mBar.getBarStartPosition() + mRearThumbPosX);
                top = padding_t + (height - mRearThumb.getMeasuredHeight()) / 2;
                right = left + mRearThumb.getMeasuredWidth();
                bottom = top + mRearThumb.getMeasuredHeight();
                mRearThumb.layout(left, top, right, bottom);
            }

            if(mPlayThumb != null && mPlayThumb.getVisibility() == View.VISIBLE) {
                left = (int) (padding_l + mBar.getBarStartPosition() - mPlayThumb.getMeasuredWidth() / 2 + mPlayThumbPosX);
                top = padding_t + (height - mPlayThumb.getMeasuredHeight()) / 2;
                right = left + mPlayThumb.getMeasuredWidth();
                bottom = top + mPlayThumb.getMeasuredHeight();
                mPlayThumb.layout(left, top, right, bottom);
            }
    }

    private void _initAttribute(AttributeSet attrs, int defStyle) {
        if (attrs == null) {
            return;
        }

        int[] ids = new int[attrs.getAttributeCount()];
        for (int i = 0; i < attrs.getAttributeCount(); i++) {
            ids[i] = attrs.getAttributeNameResource(i);
        }

        TypedArray a = mContext.obtainStyledAttributes(attrs, ids, defStyle, 0);

        for (int i = 0; i < attrs.getAttributeCount(); i++) {
            String attrName = attrs.getAttributeName(i);
            if (attrName == null)
                continue;

        }

        a.recycle();
    }

    private void _changeThumb(int x) {
        mHandler.obtainMessage();
        Message msg = mHandler.obtainMessage();
        msg.what = MSG_CHANGE_THUMB;
        msg.arg1 = x;
        mHandler.sendMessage(msg);
    }

    private int     mDownPosX;
    private int     mDownThumbPosX;
    private View    mDownView;

    private int     mDoubleTapCnt;
    private int     mDoubleTapBoundary;
    private long    mDoubleTapCurrTimeMs;
    private long    mDoubleTapPrevTimeMs;

    private static final int DOUBLE_TAP_TIMEOUT = ViewConfiguration.getDoubleTapTimeout() + 100;

    private OnTouchListener thumbTouchListener = new OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            switch(mThumbMode) {
                case THUMB_JOIN :
                    return _onTouchJoin(v, event);
                case THUMB_DISJOIN :
                    return _onTouchDisjoin(v, event);
            }
            return false;
        }
    };

    private boolean mLongPressIsEnabled;
    private int     mLongPressBoundary;
    private static final int LONGPRESS_TIMEOUT = ViewConfiguration.getLongPressTimeout();

    private void _longpressDown() {
        mHandler.removeMessages(MSG_LONG_PRESS);
        mHandler.sendEmptyMessageDelayed(MSG_LONG_PRESS, LONGPRESS_TIMEOUT);
        mLongPressIsEnabled = true;
    }

    private void _longpressMove() {
        if(mLongPressIsEnabled) {
            if(mDownView == mFrontThumb && Math.abs(mDownThumbPosX - mFrontThumbPosX) > mLongPressBoundary) {
                mLongPressIsEnabled = false;
                mHandler.removeMessages(MSG_LONG_PRESS);
            } else if(mDownView == mRearThumb && Math.abs(mDownThumbPosX - mRearThumbPosX) > mLongPressBoundary) {
                KhLog.d("_longpressMove() "+mLongPressIsEnabled+" ");
                mLongPressIsEnabled = false;
                mHandler.removeMessages(MSG_LONG_PRESS);
            }
        }
    }

    private void _longpressUp() {
        KhLog.d("_longpressUp() "+mLongPressIsEnabled+" ");
        if(mLongPressIsEnabled) {
            mLongPressIsEnabled = false;
            mHandler.removeMessages(MSG_LONG_PRESS);
        }
    }

    private void _doubletapDown() {
        if(mDoubleTapCnt > 0) {
            mDoubleTapPrevTimeMs = mDoubleTapCurrTimeMs;
        }
        mDoubleTapCurrTimeMs = System.currentTimeMillis();
        mDoubleTapCnt++;
    }

    private void _doubletapMove() {
        if(mDoubleTapCnt > 0) {
            if(mDownView == mFrontThumb && Math.abs(mDownThumbPosX - mFrontThumbPosX) > mDoubleTapBoundary) {
                mDoubleTapCnt = 0;
            } else if(mDownView == mRearThumb && Math.abs(mDownThumbPosX - mRearThumbPosX) > mDoubleTapBoundary) {
                mDoubleTapCnt = 0;
            }
        }
    }

    private void _doubletapUp() {
        if(mDoubleTapCnt > 1 && System.currentTimeMillis() - mDoubleTapPrevTimeMs < DOUBLE_TAP_TIMEOUT) {
            mDoubleTapCnt = 0;
            _doThumbModeChange();
        }
    }

    private void _doThumbModeChange() {
        KhLog.i("VideoSeekBarLayout_Kh : _doThumbModeChange");
        if(mThumbMode == THUMB_JOIN) {
            mThumbMode = THUMB_DISJOIN;
            mPlayThumb.setVisibility(View.VISIBLE);
            mPlayThumbPosX = mFrontThumbPosX;
            if(mDownView == mFrontThumb) {
                mRearThumb.setPressed(false);
            } else if(mDownView == mRearThumb) {
                mFrontThumb.setPressed(false);
            }
        } else if(mThumbMode == THUMB_DISJOIN) {
            mPlayThumb.setVisibility(View.GONE);
            mThumbMode = THUMB_JOIN;
            if(mDownView == mFrontThumb) {
                mRearThumbPosX = mFrontThumbPosX;
                mRearThumb.setPressed(true);
            } else if(mDownView == mRearThumb) {
                mFrontThumbPosX = mRearThumbPosX;
                mFrontThumb.setPressed(true);
            }

            requestLayout();
        }

    }

    private boolean _onTouchJoin(View v, MotionEvent event) {
        if(v == mFrontThumb || v == mRearThumb) {
            int action = event.getAction();
            int posX = (int) event.getX();

            switch(action) {
                case MotionEvent.ACTION_DOWN :
                    mDownPosX = posX;
                    mDownThumbPosX = mFrontThumbPosX;
                    if(mDownView != v) {
                        mDownView = v;
                    }
                    mFrontThumb.setPressed(true);
                    mRearThumb.setPressed(true);

                    _longpressDown();
                    _doubletapDown();
                    return true;
                case MotionEvent.ACTION_MOVE : {
                    int prevPos = mFrontThumbPosX;
                    mFrontThumbPosX = mFrontThumbPosX + posX - mDownPosX;

                    if(mFrontThumbPosX < 0) {
                        mFrontThumbPosX = 0;
                    } else if(mFrontThumbPosX > mBarMaxWidth) {
                        mFrontThumbPosX = mBarMaxWidth;
                    }
                    mRearThumbPosX = mFrontThumbPosX;

                    _longpressMove();
                    _doubletapMove();

                    if(prevPos != mFrontThumbPosX) {
                        _changeThumb(mFrontThumbPosX);
                        requestLayout();
                    }
                } return true;
                case MotionEvent.ACTION_UP :
                case MotionEvent.ACTION_CANCEL :
                    mFrontThumb.setPressed(false);
                    mRearThumb.setPressed(false);

                    _longpressUp();
                    _doubletapUp();
                    return true;
            }
        }
        return true;
    }

    private boolean _onTouchDisjoin(View v, MotionEvent event) {
        if(v == mFrontThumb) {
            int action = event.getAction();
            int posX = (int) event.getX();

            switch(action) {
                case MotionEvent.ACTION_DOWN :
                    mDownPosX = posX;
                    mDownThumbPosX = mFrontThumbPosX;
                    if(mDownView != v) {
                        mDownView = v;
                        mDoubleTapCnt = 0;
                    }
                    mFrontThumb.setPressed(true);

                    _longpressDown();
                    _doubletapDown();
                    return true;
                case MotionEvent.ACTION_MOVE : {
                    int prevPos = mFrontThumbPosX;
                    mFrontThumbPosX = mFrontThumbPosX + posX - mDownPosX;
                    mFrontThumbPosX = mFrontThumbPosX < mRearThumbPosX ? mFrontThumbPosX : mRearThumbPosX;

                    if(mFrontThumbPosX < 0) {
                        mFrontThumbPosX = 0;
                    } else if(mFrontThumbPosX > mBarMaxWidth) {
                        mFrontThumbPosX = mBarMaxWidth;
                    }

                    if(mPlayThumbPosX < mFrontThumbPosX) {
                        mPlayThumbPosX = mFrontThumbPosX;
                    }

                    _longpressMove();
                    _doubletapMove();

                    if(prevPos != mFrontThumbPosX) {
                        _changeThumb(mFrontThumbPosX);
                        requestLayout();
                    }
                } return true;
                case MotionEvent.ACTION_UP :
                case MotionEvent.ACTION_CANCEL :
                    mFrontThumb.setPressed(false);

                    _longpressUp();
                    _doubletapUp();
                    return true;
            }
        } else if(v == mRearThumb) {
            int action = event.getAction();
            int posX = (int) event.getX();

            switch(action) {
                case MotionEvent.ACTION_DOWN :
                    mDownPosX = posX;
                    mDownThumbPosX = mRearThumbPosX;
                    if(mDownView != v) {
                        mDownView = v;
                        mDoubleTapCnt = 0;
                    }
                    mRearThumb.setPressed(true);

                    _longpressDown();
                    _doubletapDown();
                    return true;
                case MotionEvent.ACTION_MOVE : {
                    int prevPos = mRearThumbPosX;
                    mRearThumbPosX = mRearThumbPosX + posX - mRearThumb.getMeasuredWidth() / 2;
                    mRearThumbPosX = mRearThumbPosX > mFrontThumbPosX ? mRearThumbPosX : mFrontThumbPosX;

                     if(mRearThumbPosX < 0) {
                         mRearThumbPosX = 0;
                    } else if(mRearThumbPosX > mBarMaxWidth) {
                        mRearThumbPosX = mBarMaxWidth;
                    }

                     if(mPlayThumbPosX > mRearThumbPosX) {
                         mPlayThumbPosX = mRearThumbPosX;
                     }

                     _longpressMove();
                     _doubletapMove();

                    if(prevPos != mRearThumbPosX) {
                        _changeThumb(mRearThumbPosX);
                        requestLayout();
                    }
                } return true;
                case MotionEvent.ACTION_UP :
                case MotionEvent.ACTION_CANCEL :
                    mRearThumb.setPressed(false);

                    _longpressUp();
                    _doubletapUp();
                    return true;
            }
        } else if(v == mPlayThumb) {
            int action = event.getAction();
            int posX = (int) event.getX();

            switch(action) {
                case MotionEvent.ACTION_DOWN :
                    mDownPosX = posX;
                    mDownThumbPosX = mPlayThumbPosX;
                    if(mDownView != v) {
                        mDownView = v;
                    }
                    mPlayThumb.setPressed(true);
                    return true;
                case MotionEvent.ACTION_MOVE : {
                    int prevPos = mPlayThumbPosX;
                    mPlayThumbPosX = mPlayThumbPosX + posX - mPlayThumb.getMeasuredWidth() / 2;

                     if(mPlayThumbPosX < mFrontThumbPosX) {
                         mPlayThumbPosX = mFrontThumbPosX;
                    } else if(mPlayThumbPosX > mRearThumbPosX) {
                        mPlayThumbPosX = mRearThumbPosX;
                    }

                    if(prevPos != mPlayThumbPosX) {
                        _changeThumb(mPlayThumbPosX);
                        requestLayout();
                    }
                } return true;
                case MotionEvent.ACTION_UP :
                case MotionEvent.ACTION_CANCEL :
                    mPlayThumb.setPressed(false);
                    return true;
            }
        }
        return false;

    }
}
